import { bluetoothPrint } from '@/utils/print/bluetooth'
import PrinterJobs from '@/utils/print/printerjobs'
import { ComponentInternalInstance } from 'vue'

export const usePrint = (params: {
  deviceId: Ref<string>
  serviceId: Ref<string>
  characteristicId: Ref<string>
  instance: ComponentInternalInstance
}) => {
  const { deviceId, serviceId, characteristicId, instance } = params

  /** 打印文字 */
  function onPrint() {
    const printerJobs = new PrinterJobs()
    printerJobs.println('开始打印了') // 打印并走纸
    printerJobs
      .setAlign('TXT_ALIGN_CT')
      .setFontSize(2, 2)
      .setUnderline(true)
      .println('居中文字-中号字体-下划线')
      .lineFeed(1) // 空白1行
      .setAlign('TXT_ALIGN_RT')
      .setFontSize(3, 3)
      .setBold(true)
      .setUnderline(false)
      .println('居右文字-大号字体-加黑')
      .lineFeed(2)
      .setAlign('TXT_ALIGN_LT')
      .setFontSize(1, 1)
      .setBold(false)
      // .setAlign("TXT_ALIGN_CT")
      // .setFontSize(2, 2)
      // .setUnderline(true)
      // .println("阿拉伯语：كيف حالك؟")
      // .lineFeed(1) // 空白1行
      .setAlign('TXT_ALIGN_CT')
      .setFontSize(1, 1)
      .setUnderline(true)
      .println('英语： hello yeke')
      .lineFeed(1) // 空白1行
      .setAlign('TXT_ALIGN_CT')
      .setFontSize(1, 1)
      .setUnderline(true)
      .println('俄语： привет')
      .lineFeed(1) // 空白1行
      .setAlign('TXT_ALIGN_CT')
      .setFontSize(1, 1)
      .setUnderline(true)
      .println('德语： Hallo, die welt.')
      .lineFeed(1) // 空白1行
      .println('打印结束')
      .lineFeed(4)
    handlePrint(printerJobs)
  }

  /** 打印条形码 */
  function onPrintBarCode() {
    const printerJobs = new PrinterJobs()
    printerJobs
      .setAlign('TXT_ALIGN_CT')
      .println("打印条形码，内容'0123456789'")
      .addBarcode({
        text: '0123456789',
        height: 20,
        textPosition: 2,
      })
      .println()
      .lineFeed(4)
    handlePrint(printerJobs)
  }

  /** 打印二维码 */
  function onPrintQrCode() {
    const printerJobs = new PrinterJobs()
    printerJobs
      .setAlign('TXT_ALIGN_CT')
      .println("打印二维码，内容'https://www.baidu.com?a=1&b=2'")
      .addQRCode({ text: 'https://www.baidu.com?a=1&b=2' })
      .println()
      .lineFeed(4)
    handlePrint(printerJobs)
  }

  /** 打印重复内容 */
  function onPrintRpeat() {
    const printerJobs = new PrinterJobs()
    const start = printerJobs.getLength()
    printerJobs.setAlign('TXT_ALIGN_CT').println('重复内容开始').println('重复内容结束')
    const end = printerJobs.getLength()
    printerJobs.repeat(start, end, 3) // 重复打印3次
    printerJobs.text('打印完成').lineFeed(4).printToEnd()
    handlePrint(printerJobs)
  }

  const canvasWidth = ref(0)
  const canvasHeight = ref(0)
  const imgPath = ref('')
  const currentTime = ref(1) // 当前次数
  const looptime = ref(0) // 总循环次数
  const singleDataSize = ref(20) // 每次循环的数据大小
  const printNum = ref(1)
  const currentPrint = ref(1)
  /** 图片打印 */
  function onPrintImg() {
    console.log('instance', instance)
    uni.showLoading({ title: '图片打印中...', mask: true })
    const ctx = uni.createCanvasContext('imgCanvas', instance)
    uni.downloadFile({
      url: 'https://yeke-admin.oss-cn-beijing.aliyuncs.com/nestjs_logo.jpg',
      success(res) {
        console.log('下载成功', res)
        if (res.statusCode === 200) {
          const tempFilePath = res.tempFilePath
          uni.getImageInfo({
            src: tempFilePath,
            success(res) {
              console.log('获取图片信息成功', res)

              imgPath.value = tempFilePath
              const getWindowInfo = uni.getWindowInfo()
              console.log('getWindowInfo', getWindowInfo)
              const winWidth = parseInt(String(getWindowInfo.windowWidth * 1))
              const newImgW = winWidth
              const newImgH = parseInt(String((winWidth / res.width) * res.height))

              canvasWidth.value = newImgW
              canvasHeight.value = newImgH
              console.log('---------', canvasWidth.value, canvasHeight.value)

              ctx.fillStyle = 'rgba(255,255,255,1)'
              ctx.clearRect(0, 0, newImgW, newImgH)
              ctx.fillRect(0, 0, newImgW, newImgH)
              // 进行绘画图片
              ctx.drawImage(tempFilePath, 0, 0, newImgW, newImgH)
              ctx.draw(false, () => {})
              console.log(canvasWidth.value, canvasHeight.value)

              setTimeout(() => {
                uni.canvasGetImageData({
                  canvasId: 'imgCanvas',
                  x: 0,
                  y: 0,
                  width: canvasWidth.value,
                  height: canvasHeight.value,
                  async success(res) {
                    console.log('获取图片数据成功', res)
                    const printerJobs = new PrinterJobs()
                    printerJobs.convertPartialToBitmap(res)
                    printerJobs.setLine()
                    printerJobs.println().lineFeed(4)

                    const time = 20
                    looptime.value = parseInt(String(printerJobs.getLength() / time) + 1)
                    handleSend(printerJobs.getQueue())
                  },
                  fail(err) {
                    console.log('获取图片数据失败', err)
                  },
                })
              }, 2000)
            },
          })
        } else {
          uni.hideLoading()
          uni.showToast({
            icon: 'error',
            title: '图片下载失败',
            mask: true,
          })
        }
        uni.hideLoading()
      },
      fail(err) {
        uni.hideLoading()
        uni.showToast({
          icon: 'error',
          title: '图片下载失败',
          mask: true,
        })
        console.log('下载失败', err)
      },
    })
  }

  /** 只有图片打印发送数据才走这个方法 */
  function handleSend(buffer: number[]) {
    let buf: any
    console.log('currentTime', currentTime.value)
    console.log('looptime', looptime.value)
    console.log('currentPrint', currentPrint.value)
    console.log('printNum', printNum.value)

    buf = new ArrayBuffer(singleDataSize.value)
    const dataView = new DataView(buf)

    for (let i = 0; i < singleDataSize.value; ++i) {
      dataView.setUint8(i, buffer[(currentTime.value - 1) * singleDataSize.value + i])
    }

    const progress = parseInt(String((currentTime.value / looptime.value) * 100))
    uni.showToast({
      icon: 'none',
      title: '进度' + progress + '%',
      mask: true,
    })
    uni.writeBLECharacteristicValue({
      deviceId: deviceId.value,
      serviceId: serviceId.value,
      characteristicId: characteristicId.value,
      value: buf,
      fail: function (e) {
        uni.showToast({
          title: '打印第' + currentPrint.value + '张失败',
          icon: 'none',
        }) // console.log(e)
      },
      complete: function () {
        currentTime.value++
        console.log(currentTime.value, looptime.value)

        if (currentTime.value <= looptime.value) {
          handleSend(buffer)
        } else {
          if (currentPrint.value === printNum.value) {
            looptime.value = 0
            currentTime.value = 1
            currentPrint.value = 1
            uni.showToast({
              title: '打印完成',
              icon: 'none',
            })
          } else {
            currentPrint.value++
            currentTime.value = 1
            handleSend(buffer)
          }
        }
      },
    })
  }

  /** 除了图片打印，其他发送数据方法 */
  function handlePrint(printerJobs: PrinterJobs) {
    console.log('printerJobs', printerJobs)

    const buffer = printerJobs.buffer()
    // 1.并行调用多次会存在写失败的可能性
    // 2.建议每次写入不超过20字节
    // 分包处理，延时调用
    const maxChunk = 20
    const delay = 20
    const length = buffer.byteLength
    for (let i = 0, j = 0; i < length; i += maxChunk, j++) {
      const subPackage = buffer.slice(i, i + maxChunk <= length ? i + maxChunk : length)
      setTimeout(writeBLECharacteristicValue, j * delay, subPackage)
    }
  }

  async function writeBLECharacteristicValue(buffer: any) {
    const params = {
      deviceId: deviceId.value,
      serviceId: serviceId.value,
      characteristicId: characteristicId.value,
      value: buffer,
    }
    console.log('writeBLECharacteristicValue', params)

    await bluetoothPrint(params)
  }

  return {
    onPrint,
    onPrintBarCode,
    onPrintQrCode,
    onPrintRpeat,
    onPrintImg,
    deviceId,
    serviceId,
    characteristicId,
    canvasWidth,
    canvasHeight,
    imgPath,
    handleSend,
    handlePrint,
    writeBLECharacteristicValue,
  }
}
